package org.finesys.common.file.client.local;

import cn.hutool.core.io.FileUtil;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import lombok.RequiredArgsConstructor;
import org.finesys.common.file.FileInfo;
import org.finesys.common.file.client.FileTemplate;
import org.finesys.common.file.properties.FileProperties;

import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 本地文件存储
 */
@RequiredArgsConstructor
public class LocalFileTemplate implements FileTemplate {
    private final FileProperties fileProperties;


    @Override
    public void createBucket(String bucketName) {
        FileUtil.mkdir(getFilePath(bucketName));
    }

    @Override
    public FileInfo putObject(String bucketName, String objectName, InputStream stream, String contextType) throws Exception {
        String bucketPath = getFilePath(bucketName);
        if (!FileUtil.isDirectory(bucketPath)) {
            createBucket(bucketName);
        }
        //写入文件
        String filePath = bucketPath + FileUtil.FILE_SEPARATOR + objectName;
        File file = FileUtil.file(filePath);
        FileUtil.writeFromStream(stream, file);
        return new FileInfo()
                .setFileId(UUID.randomUUID().toString())
                .setFileName(objectName)
                .setOriginalFileName(objectName)
                .setBasePath(bucketName)
                .setUrl(filePath)
                .setSize(stream.available())
                .setFileType(contextType);
    }

    @Override
    public FileInfo putObject(String bucketName, String objectName, InputStream stream) throws Exception {
        return putObject(bucketName, objectName, stream, null);
    }

    @Override
    public void removeBucket(String bucketName) {
        String dirPath = getFilePath(bucketName);
        FileUtil.del(dirPath);
    }

    @Override
    public void removeObject(String bucketName, String objectName) throws Exception {
        String dirPath = getFilePath(bucketName);
        String filePath = dirPath + FileUtil.FILE_SEPARATOR + objectName;
        FileUtil.del(filePath);
    }

    @Override
    public S3Object getObject(String bucketName, String objectName) {
        String dirPath = getFilePath(bucketName);
        String filePath = dirPath + FileUtil.FILE_SEPARATOR + objectName;
        S3Object s3Object = new S3Object();
        s3Object.setBucketName(bucketName);
        s3Object.setKey(objectName);
        s3Object.setObjectContent(FileUtil.getInputStream(filePath));
        return s3Object;
    }

    @Override
    public List<Bucket> getAllBuckets() {
        String basePath = fileProperties.getLocal().getBasePath();
        return Arrays.stream(FileUtil.ls(basePath)).filter(file -> file.isDirectory()).map(dir -> new Bucket(dir.getName())).collect(Collectors.toList());
    }

    @Override
    public List<S3ObjectSummary> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
        String dirPath = getFilePath(bucketName);
        File[] files = FileUtil.ls(dirPath);
        //查找第一级目录中匹配的数据
        List<S3ObjectSummary> listFiles = Arrays.stream(files).filter(file -> file.getName().startsWith(prefix)).map(file -> {
            S3ObjectSummary s3ObjectSummary = new S3ObjectSummary();
            s3ObjectSummary.setBucketName(bucketName);
            s3ObjectSummary.setKey(file.getName());
            return s3ObjectSummary;
        }).collect(Collectors.toList());
        //递归查找
        if (recursive) {
            Arrays.stream(files).filter(file -> file.isDirectory()).forEach(file -> getChildFile(file.getPath(), prefix, true, listFiles));
        }
        return listFiles;
    }

    /**
     * 获取路径下的文件列表
     */
    private void getChildFile(String rootPath, String prefix, boolean validPrefix, List<S3ObjectSummary> list) {
        File[] files = FileUtil.ls(rootPath);
        Arrays.stream(files).forEach(file -> {
            S3ObjectSummary s3ObjectSummary = new S3ObjectSummary();
            s3ObjectSummary.setBucketName(rootPath);
            s3ObjectSummary.setKey(file.getName());
            //验证前缀
            if (validPrefix) {
                if (file.getName().startsWith(prefix)) {
                    //文件夹继续找
                    if (file.isDirectory()) {
                        getChildFile(file.getPath(), prefix, false, list);
                    } else {
                        list.add(s3ObjectSummary);
                    }
                } else {
                    //文件夹继续找
                    if (file.isDirectory()) {
                        getChildFile(file.getPath(), prefix, true, list);
                    }
                }
            } else {
                //无需验证
                //文件夹继续找
                if (file.isDirectory()) {
                    getChildFile(file.getPath(), prefix, false, list);
                }
                list.add(s3ObjectSummary);
            }
        });
    }

    @Override
    public String shareObjectPreSignedURL(String bucketName, String objectName) {
        return shareObjectPreSignedURL(bucketName, objectName, 7);
    }

    @Override
    public String shareObjectPreSignedURL(String bucketName, String objectName, Integer expires) {
        String filePath = getFilePath(bucketName) + FileUtil.FILE_SEPARATOR + objectName;
        boolean success = FileUtil.exist(filePath);
        return success ? filePath : null;
    }

    /**
     * 获取目录URL
     */
    public String getFilePath(String bucketName) {
        return fileProperties.getLocal().getBasePath() + FileUtil.FILE_SEPARATOR + bucketName;
    }
}
